package com.aiguigu.test;

import jdk.nashorn.internal.objects.annotations.Getter;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/*
* 1.构造器私有化
* 2.自行创建,且用静态变量保存
* 3.向外提供这个实例
*饿汉式  懒汉式
* */
public class inrc {
    public static CountDownLatch countDownLatch = new CountDownLatch(6);
    public static void main(String[] args) throws InterruptedException {



        /*Callable<lanhanshi> callable = new Callable<lanhanshi>() {
            @Override
            public lanhanshi call() throws Exception {
                return lanhanshi.getInstance();
            }
        };
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        Future<lanhanshi> f1 = executorService.submit(callable);
        Future<lanhanshi> f2 = executorService.submit(callable);*/

      /*  CountDownLatchDemo countDownLatch1 = new CountDownLatchDemo();
        countDownLatch1.Test();
        countDownLatch.await();
        System.out.println("班长锁门");*/

      PC pc = new PC();
      new Thread(()->{
          pc.print5();
      },"A").start();

        new Thread(()->{
           pc.print10();
        },"B").start();

        new Thread(()->{
           pc.print15();
        },"C").start();
    }
}
class singlten{
    public  static final singlten INSTANCE = new singlten();
    private singlten(){

    }
}

enum singlten2{
    INSTANCE
}


class lanhanshi{

    private volatile static lanhanshi instance;


    private lanhanshi(){

    }

    public static  lanhanshi getInstance(){
        //DCL双端检测机制 加锁前后都判断一次
        if (instance == null){

            synchronized (lanhanshi.class){
                if (instance == null){
                    instance = new lanhanshi();
                }
            }
        }
             return instance;
    }

}

class LanHan2{
    private LanHan2(){}
//因为是在内部类加载的,因此是线程安全的
    private static class Inner{
        private static final LanHan2 LAN_HAN_2 = new LanHan2();
    }

    public static  LanHan2 getInstance(){
        return Inner.LAN_HAN_2;
    }
}

class SpinLockDemo{
    AtomicReference<Thread> atomicReference = new AtomicReference<>();

    public void MyLock(){
        Thread thread = Thread.currentThread();
        while (!atomicReference.compareAndSet(null,thread)){

        }
    }

    public void MyunLock(){
        Thread thread = Thread.currentThread();
        atomicReference.compareAndSet(thread,null);
    }
}

class CountDownLatchDemo{
    public void Test(){

        for (int i = 0; i < 6; i++) {
            new Thread(()->{
                System.out.println(Thread.currentThread().getName()+"\t上完自习,离开教师");
                inrc.countDownLatch.countDown();
            },String.valueOf(i)).start();
        }
    }
}

enum CountryEnum{
    ONE(1,"其");
    private Integer code;
     private String message;

    CountryEnum(Integer code, String message) {
        this.code = code;
        this.message = message;
    }

    public Integer getCode() {
        return code;
    }

    public String getMessage() {
        return message;
    }
}

class CyclicBarrierDemo{
    CyclicBarrier cyclicBarrier = new CyclicBarrier(7,()->{
        System.out.println("召唤龙珠");
    });
}

class SemaphoreDemo{
     Semaphore semaphore = new Semaphore(3);
     
     public void testSem(){
         for (int i = 0; i < 7; i++) {
             try {
                 semaphore.acquire();
                 //do
             }catch (Exception e){
                 e.printStackTrace();
             }finally {
                 semaphore.release();
             }
         }
     }
}


class BlockQueueDemo{
    //collect ->blockQueue
    BlockingQueue<String> blockingQueue = new SynchronousQueue<>();

    public void testBlockQueue(){
        new Thread(()->{
            try {
                blockingQueue.put("1");
                blockingQueue.put("2");
                blockingQueue.put("3");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"aaa").start();

        new Thread(()->{
            try {
                blockingQueue.take();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"bbb").start();
    }
}

class ShareDate{
    private  int number = 0;

    private  Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();
    //线程 操作 资源类
    //判断 干活 通知
    //防止虚假唤醒  wait notify  shiobject类的  判断时要用while 不能用if
    public void Increment() throws Exception{
        lock.lock();
        try {
            while (number != 0){
                //等待,不能生产
                condition.await();
            }
            number++;
            System.out.println(number);
            condition.signalAll();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }

    }

    public void Decrement() throws Exception{
        lock.lock();
        try {
            while (number == 0){
                //等待,不能生产
                condition.await();
            }
            number--;
            System.out.println(number);
            condition.signalAll();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }

    }

}

class PC{
    private Integer number = 1;
    private Lock lock = new ReentrantLock();
    private Condition c1 = lock.newCondition();
    private Condition c2 = lock.newCondition();
    private Condition c3 = lock.newCondition();

    public void print5(){
        lock.lock();
        try {
            while (number != 1){
                c1.await();
            }
            for (int i = 0; i < 5; i++) {
                System.out.print(Thread.currentThread().getName()+"\t"+i+" ");
            }
            number = 2;
            c2.signal();
        }catch (Exception e){
           e.printStackTrace();
        }finally {
           lock.unlock();
        }
    }

    public void print10(){
        lock.lock();
        try {
            while (number != 2){
                c2.await();
            }
            for (int i = 0; i < 10; i++) {
                System.out.print(Thread.currentThread().getName()+"\t"+i+" ");
            }
            number = 3;
            c3.signal();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public void print15(){
        lock.lock();
        try {
            while (number != 3){
                c3.await();
            }
            for (int i = 0; i < 15; i++) {
                System.out.print(Thread.currentThread().getName()+"\t"+i+" ");
            }
            number = 1;
            c1.signal();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

}

class MyResource{
    private volatile boolean FLAG = true;
    private AtomicInteger integer = new AtomicInteger();

    BlockingQueue<String> blockingQueue = null;

    public MyResource(BlockingQueue<String> blockingQueue) {
        this.blockingQueue = blockingQueue;
        System.out.println(blockingQueue.getClass().getName());
    }

    public void MyPord()throws Exception{
        String data = null;
        boolean retValue;

        while (FLAG){
            data = integer.incrementAndGet()+"";
            retValue = blockingQueue.offer(data,2L,TimeUnit.SECONDS);

            if (retValue){
                System.out.println(Thread.currentThread().getName()+"插入"+data+"成功");
            }else {
                System.out.println(Thread.currentThread().getName()+"插入"+data+"失败");
            }
            TimeUnit.SECONDS.sleep(1);
        }
        System.out.println(Thread.currentThread().getName()+"大老板叫停了,生产动作结束");
    }

    public void Cons()throws Exception{
        while (FLAG){
            String poll = blockingQueue.poll(2L, TimeUnit.SECONDS);
            if (poll == null || poll.equalsIgnoreCase("")){
                FLAG = false;
                System.out.println(Thread.currentThread().getName()+"超时");
            }
            System.out.println(Thread.currentThread().getName()+"消费队列"+poll+"成功");
        }
    }
}